#define _USE_MATH_DEFINES
#include <math.h>
#include <stdint.h>

#include "raycaster.h"
#include "map.h"
#include "ray.h"
#include "player.h"
#include "wall.h"

int isGameRunning = 0;
int ticksLastFrame;

void setup()
{
  loadWallTextures();
  loadMap("level.map");
}

void processInput()
{
  SDL_Event event;
  SDL_PollEvent(&event);
  switch (event.type)
  {
  case SDL_QUIT:
    isGameRunning = 0;
    break;
  case SDL_KEYDOWN:
    switch (event.key.keysym.sym)
    {
    case SDLK_ESCAPE:
      isGameRunning = 0;
      break;
    case SDLK_UP:
      player.walkDirection = 1;
      break;
    case SDLK_DOWN:
      player.walkDirection = -1;
      break;
    case SDLK_LEFT:
      player.turnDirection = -1;
      break;
    case SDLK_RIGHT:
      player.turnDirection = 1;
      break;
    default:
      break;
    }
    break;
  case SDL_KEYUP:
    switch (event.key.keysym.sym)
    {
    case SDLK_UP:
      player.walkDirection = 0;
      break;
    case SDLK_DOWN:
      player.walkDirection = 0;
      break;
    case SDLK_LEFT:
      player.turnDirection = 0;
      break;
    case SDLK_RIGHT:
      player.turnDirection = 0;
      break;
    default:
      break;
    }
  }
}

void update()
{

  float deltaTime;
  int timeToWait = FRAME_TIME_LENGTH - (SDL_GetTicks() - ticksLastFrame);
  if (timeToWait > 0 && timeToWait <= FRAME_TIME_LENGTH)
    SDL_Delay(timeToWait);

  deltaTime = (SDL_GetTicks() - ticksLastFrame) / 1000.0f;
  ticksLastFrame = SDL_GetTicks();
  movePlayer(deltaTime);
  castAllRays();
}

void render()
{
  clearColourBuffer(0);
  renderWallProjection();

  // display the minimap
  // renderMap();
  // renderRays();
  // renderPlayer();

  renderColourBuffer();
}

void releaseResources(void)
{
  freeWallTextures();
  destroyWindow();
}

int main(int argc, char **argv)
{
  isGameRunning = initialiseWindow();
  setup();
  while (isGameRunning)
  {
    processInput();
    update();
    render();
  }
  releaseResources();
  return 0;
}
